from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
import re,string,random,redis,jwt,time
from .models import User,Addr
from captcha.image import ImageCaptcha
from django.http import HttpResponse
from django.contrib.auth import authenticate
from django.contrib.auth.hashers import check_password
from django.conf import settings
from .serializer import UserSer,AddrSer
from rest_framework_jwt.utils import jwt_payload_handler,jwt_encode_handler
from django.db.models import Q
from django.db import models
from decorator.decorator import check_login
from django.contrib.auth.hashers import check_password



# Create your views here.

# 用户表
#    id   username     password      phone
# int pk   varchar(50) varchar(100)  varchar(11)



# class Logout(APIView):
#     def post(self,request):
#         return Response({"code":200,'msg':'测试django的跨域'})
#     def get(self,request):
#         return Response({"code":200,'msg':'测试sfvdgo的跨域'})


# 校验用户名是否重复
class CheckUsername(APIView):
    # def get(self,request,username):
    #     # 查询当前用户名是否存在
    #     try:
    #         User.objects.get(username=username)
    #     except:
    #         return Response({"code":200,'msg':'用户名可以使用'})
    #
    #     return Response({"code":204,'msg':'用户名已被注册'})
    def get(self,request,username):
        # 1.判断用户名格0式
        if not re.match(r'^[a-zA-Z][a-zA-Z0-9_]{4,15}$',username):
            return Response({"code":404,'msg':'用户名格式不正确'})
        # 2.根据用户名查询用户
        n = User.objects.filter(username=username).count()
        # 3. 判断
        if n == 0:
            return Response({"code":200,'msg':'用户名符合要求'})
        else:
            return Response({"code":400,'msg':'用户名重复'})

# 校验手机号的重复性
class CheckMobile(APIView):
    def get(self,request,mobile):

        # 1.验证手机号是否满足规则
        # 手机号以1开头，第二位3-9之间的数字，长度为11，只允许数字
        if not re.findall(r"^1[3-9]\d{9}$", mobile):
            return Response({"code":204,'msg':'手机号不合法'})

        # 2.根据手机号查询用户，如果能查询到用户，说明已经注册
        # 手机号 不能再注册
        user_query_set = User.objects.filter(mobile=mobile)

        if not user_query_set:
            return Response({"code":200 , 'msg':'可以正常注册'})

        return Response({"code":200,'msg':'用户名可以使用'})


# 图片验证码
class GenImageCode(APIView):
    def get(self,request,uuid):
        print("uuid",uuid,type(uuid))

        # 1.生成随机字符串
        alpha_number = string.ascii_letters+string.digits
        img_code = "".join(random.sample(alpha_number,4))
        print("image_code:",img_code)

        # 2.生成图片验证码
        img_cap = ImageCaptcha()
        img_code_captcha = img_cap.generate(img_code)
        print("img_code:",img_code_captcha)

        # 3.存储图片验证码
        redis_conn = redis.Redis(host='localhost',port=6379,db=0,password='123')
        key = "image_code:%s"%uuid
        redis_conn.set(key,img_code,ex=300)
        redis_conn.close()

        return HttpResponse(img_code_captcha,content_type="image/png")


# 校验图片验证码
class CheckImageCode(APIView):
    def get(self,request):
        # 1.获取前端数据
        uuid_ = request.query_params.get("imageCodeID")
        image_code = request.query_params.get("imageCode")

        # 2.根据uuid 构造key
        key = "image_code:%s" % uuid_

        # 3.读入redis存储的验证码
        redis_conn = redis.Redis(host='localhost',port=6379,db=0,password='123')
        stored_image_clde = redis_conn.get(key)
        if not stored_image_clde:
            return Response({'code':204,'msg':'图片验证码已过期'})
        print("验证码：",stored_image_clde)

        if stored_image_clde.decode().lower() == image_code.lower():
            return Response({"code":200,'msg':'验证成功'})

        return Response({"code":204,'msg':'验证码输入错误'})


# 用户注册
class Register(APIView):
    def post(self,request):
        # 1.获取前端数据
        username = request.data.get("userName")
        password = request.data.get('pwd')
        mobile = request.data.get("mobile")
        aggrement = request.data.get('agree')

        # 2.简单验证
        if not all([username,password,mobile,aggrement]):
            return Response({'code':204,'msg':'用户信息不完整'})


        # 3.创建用户对象，并存储
        User.objects.create_user(username=username,password=password,mobile=mobile)

        return Response({"code":200,'msg':'注册成功！'})


# 用户登录
class Login(APIView):
    def post(self,request):

        # 1.获取前端数据
        username = request.data.get('user')
        password = request.data.get('pwd')

        # 2.查询用户
        try:
            user = User.objects.get(Q(username=username) | Q(mobile=username))
        except:
            return Response({"code":204,'msg':'用户不存在'})

        # 3.验证密码
        validate = check_password(password,user.password)
        if validate:
            # 验证通过，允许登录
            # request.session['username'] = username
            token = self.gen_token(user)
            return Response({"code":200,'msg':'欢迎%s'%username,'user':{"userName":user.username},'token':token})

        return Response({"code":204,"msg":'用户名或者密码错误'})

    @staticmethod
    def gen_token(user):
        # 组织payload数据
        payload = {
            'username':user.username,
            'exp': time.time() + 3000
        }

        # 使用jwt编码，生成token
        token = jwt.encode(payload=payload, key=settings.SECRET_KEY,algorithm='HS256')
        return token

# 退出登录
class Logout(APIView):
    def get(self,request):

        if request.session.get('username'):
            # 删除服务端的session信息
            del request.session['username']

        return Response({'code':200,'msg':'退出登录'})


# 用户中心:获取用户信息

class UserAPIVIew(APIView):
    @check_login
    def get(self, request):
        # 1.获取用户对象
        user = request.user
        # 2.查询用户的收获地址
        addr_queryset = user.addr_set.all()
        addr_queryset_ser = AddrSer(addr_queryset, many=True)
        # 3.组织响应的q`数据结构
        data = {
            "code": 200,
            'msg': "获取用户信息成功！",
            "userInfo": {
                "username":user.username,
                "phone":user.mobile,
                "addrs":addr_queryset_ser.data,
            }
        }

        # 4.返回响应
        return Response(data)


    # 更新用户信息
    @check_login
    def put(self,request):

        # 1.获取用户对象
        user = request.user

        # 2.获取前端数据 phone addrs
        phone = request.data.get("phone")
        addrs = request.data.get("addrs")

        # 3.更新用户的信息
        update_user = False
        update_addr = False

        # 用户信息的更新
        if user.mobile != phone:
            user.mobile = phone
            user.save()
            update_user = True

        # 地址信息的更新
        for addr in addrs:
            addr_queryset = Addr.objects.filter(id=addr.get("id"), receiver=addr.get("receiver"),
                                    receive_mobile=addr.get("receive_mobile"), receive_addr=addr.get("receive_addr"),
                                    user=user)
            if not addr_queryset:
                r = Addr.objects.filter(id=addr.get("id")).update(receiver=addr.get("receiver"),
                                    receive_mobile=addr.get("receive_mobile"), receive_addr=addr.get("receive_addr"),
                                    user=user)

                update_addr = True if r else False

        # 4.返回响应
        if not update_user and not update_addr:
            return Response({"code":204, 'msg':'用户信息未作更改！'})

        return Response({'code':200, 'msg':'用户信息更新成功！'})

# 用户中心：收获地址
class AddrAPIView(APIView):
    # 添加收获地址
    @check_login
    def post(self, request):

        # 1.获取用户对象
        user = request.user

        # 2.获取前端数据
        receiver = request.data.get("receiver")
        receive_mobile = request.data.get("receive_mobile")
        receive_addr = request.data.get("receive_addr")
        is_default = request.data.get("is_default")

        if not all([receiver, receive_mobile, receive_addr]):
            return Response({"code":204, 'msg':'地址信息不完整'})

        # 3.创建地址对象， 存储地址数据
        if is_default:
            Addr.objects.filter(user=user).update(is_default=False)

        # 解决地址重复添加的问题
        addr_queryset = Addr.objects.filter(receiver=receiver, receive_mobile=receive_mobile, receive_addr=receive_addr, user=user)
        if addr_queryset:
            return Response({"code":204, 'msg':"地址已存在"})

        # 创建地址对象，并存储
        addr = Addr.objects.create(receiver=receiver, receive_mobile=receive_mobile, receive_addr=receive_addr,
                                   is_default=is_default, user=user)
        addr_ser = AddrSer(addr)
        # 4.组织响应的数据结构
        data = {
                'code': 200,
                'msg':"添加地址成功！",
                "addr":addr_ser.data,
        }
        # 5.返回响应
        return Response(data)

    # @check_login
    def delete(self, request):

        # 1.获取地址id
        addr_id = request.data.get("addr_id")

        # 2.查询当前的地址， 并删除
        Addr.objects.get(id=addr_id).delete()


        return Response({"code":200, 'msg':'删除地址成功'})

    # 加载用户的收获地址
    @check_login
    def get(self,request):
        # 1.获取用户对象
        user = request.user
        # 2.反向查询该用户的所有的收获地址
        addr_queryset = user.addr_set.all()
        addr_queryset_ser = AddrSer(addr_queryset, many=True)
        # 3.组织响应的数据结构
        data = {
            "code": 200,
            'msg': "获取收获地址成功！",
            "addrList": addr_queryset_ser.data
        }

        # 4.返回响应

        return Response(data)


# 修改密码的视图类

class PasswordAPIView(APIView):

    # 接收put请求
    def put(self, request):

        # 1.获取前端数据
        username = request.data.get("user")
        origin_pw = request.data.get("originPw")
        new_pw = request.data.get("newPw")
        confirm_new_pw = request.data.get('confirmNewPw')

        print(username)
        print(origin_pw)
        print(new_pw)
        print(confirm_new_pw)
        # 2.数据校验
        if not all([username, origin_pw, new_pw, confirm_new_pw]):
            return Response({"code":204, "msg":"信息不完整"})

        # 用户是否存在
        try:
            user = User.objects.get(username=username)
        except:
            return Response({"code":204, 'msg':'用户不存在'})

        # check_password 校验用户的密码
        validate = check_password(origin_pw, user.password)
        if not validate:
            return Response({"code":204, 'msg':'用户名或者密码不正确'})

        # 验证两次的新密码是否一致
        if new_pw != confirm_new_pw:
            return Response({"code":204, 'msg':'两次密码不一致'})

        # 3.修改用户的密码
        user.set_password(new_pw)
        user.save()

        # 4.返回响应
        return Response({"code":200, 'msg':'密码修改成功'})




import random
# from users.utils import send_message
from users.tasks import send_message

class SmsCodeView(APIView):

    def post(self, request):

        # 1. 接受前端数据
        mobile = request.data.get("mobile")
        uuid_ = request.data.get("uuid")

        # 2. 生成随机验证码
        sms_code = random.randint(1000, 99999)
        expire = 10

        # 3. 给容联云发送请求
        # result = send_message(sms_code, mobile, expire)
        # 提交异步任务
        result = send_message.delay(sms_code, mobile, expire)

        # 4. 判断短信是否发送成功
        # if result:
        #     # 成功发送 ， 存储sms_code---->redis
        #     sms_key = "sms_%s" %uuid_
        #     redis_cli = redis.Redis(host="localhost",port=6379, password='123', db=3)
        #     redis_cli.set(sms_key, sms_code)
        #
        #     return Response({"code":200,"msg":'短信发送成功'})
        #
        # else:
        #
        #     return Response({"code":400,'msg':'短信发送失败'})

        # 存储短信验证码
        redis_cli = redis.Redis(host="localhost", port=6379, password='123', db=3)
        sms_key = "sms_%s"%uuid_
        redis_cli.set(sms_code, sms_key)
        return Response({"code": 200, 'msg': '短信已发送，请注意查收'})













